/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#include "SceneWindow.h"

#include <QtCore/QTime>
#include <QtGui/QEvent.h>
#include <QtGui/QMessageBox>

#include "ProjectManager.h"

#include "GameBuilder.h"
#include "BuilderUtil.h"

namespace PQBuilder
{
	SceneWindow::SceneWindow(QWidget *parent,Qt::WindowFlags flag)
		:QWidget(parent,flag),_inited(false)
	{
		setAcceptDrops(true);
		setContextMenuPolicy(Qt::PreventContextMenu );

		setFocusPolicy(Qt::WheelFocus);
		setMouseTracking(true);
		setAttribute(Qt::WA_NoBackground);
		setAttribute(Qt::WA_PaintOnScreen);
		setTimer();

		setMinimumSize(800,600);
	}

	void SceneWindow::setTimer()
	{
		startTimer(50);//100 msec 0.1 sec 10frame/second max frame rate
		
		QTime time = QTime::currentTime();
		unsigned int curtime = time.hour() * 60 + time.minute();
		curtime = (curtime * 60) + time.second();
		curtime = (curtime * 1000) + time.msec();
		_lastTime=curtime;
	}

	 void SceneWindow::timerEvent(QTimerEvent *evt)
	 {
		 if(!this->isActiveWindow()){
			 return;
		 }

		 int id=evt->timerId();

		QTime time = QTime::currentTime();
		unsigned int curtime = time.hour() * 60 + time.minute();
		curtime = (curtime * 60) + time.second();
		curtime = (curtime * 1000) + time.msec();

		unsigned int deltaT = curtime - _lastTime;
        _lastTime = curtime;

		this->updateScene((float)deltaT/1000.0f);
	 }

	 void SceneWindow::updateScene(float deltaT)
	 {
		 SGameBuilder.update(deltaT);
		 QWidget::update();
	 }

	 void SceneWindow::activeScene()
	 {
		 if(!_inited){
			SGameBuilder.init(Ogre::StringConverter::toString((size_t)this->winId()),this->width(),this->height());
		}
		 SGameBuilder.activate();
	 }

	SceneWindow::~SceneWindow()
	{
		destroy();
	}

	void SceneWindow::paintEvent(QPaintEvent* evt)
	{
		if(!_inited){
			SGameBuilder.init(Ogre::StringConverter::toString((size_t)this->winId()),this->width(),this->height());
		}
		
		SGameBuilder.renderOneFrame();
	}

	QPaintEngine* SceneWindow::paintEngine() const
	{
		return 0;
	}


	void SceneWindow::resizeEvent(QResizeEvent* evt)
	{
		SGameBuilder.ResetScreenResolution(width(),height());
	}

	void SceneWindow::focusInEvent(QFocusEvent *evt)
	{
		SGameBuilder.ResetInput();
		QWidget::update();
	}

	void SceneWindow::focusOutEvent(QFocusEvent *evt)
	{
		SGameBuilder.ResetInput();
		QWidget::update();
		
	}

	void SceneWindow::keyPressEvent(QKeyEvent *evt)
	{
		
		SGameBuilder.OnKeyDown(translateQtKey(evt->key()));
		QWidget::update();
	}

	void SceneWindow::keyReleaseEvent(QKeyEvent *evt)
	{
		SGameBuilder.OnKeyUp(translateQtKey(evt->key()));
		QWidget::update();
	}

	void SceneWindow::mouseMoveEvent(QMouseEvent *evt)
	{
		if(!hasFocus()){
			setFocus();
		}
		SGameBuilder.OnMouseMove(evt->x(),evt->y());
		QWidget::update();
	}

	void SceneWindow::mousePressEvent(QMouseEvent *evt)
	{
		if(!hasFocus()){
			setFocus();
		}
		if(evt->button() == Qt::LeftButton){
			SGameBuilder.OnMouseLeftDown(evt->x(),evt->y());
		}else if(evt->button() == Qt::RightButton){
			SGameBuilder.OnMouseRightDown(evt->x(),evt->y());
		}else if(evt->button() == Qt::MidButton){
			SGameBuilder.OnMouseMidDown(evt->x(),evt->y());
		}

		QWidget::update();
	}

	void SceneWindow::mouseReleaseEvent(QMouseEvent *evt)
	{
		if(!hasFocus()){
			setFocus();
		}
		if(evt->button() == Qt::LeftButton){
			SGameBuilder.OnMouseLeftUp(evt->x(),evt->y());
		}else if(evt->button() == Qt::RightButton){
			SGameBuilder.OnMouseRightUp(evt->x(),evt->y());
		}else if(evt->button() == Qt::MidButton){
			SGameBuilder.OnMouseMidUp(evt->x(),evt->y());
		}

		QWidget::update();
	}

	void SceneWindow::leaveEvent(QEvent *evt)
	{
	}

	void SceneWindow::wheelEvent(QWheelEvent *evt)
	{
	}

	void SceneWindow::dragLeaveEvent(QDragLeaveEvent *evt)
	{
		
	}

	void SceneWindow::dragMoveEvent(QDragMoveEvent *evt)
	{
		int x=evt->pos().x();
		int y=evt->pos().y();

		assert(false);
		/*
		if (evt->mimeData()->hasFormat(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE))) { 
			QByteArray bytes=evt->mimeData()->data(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE));
			SGameBuilder.OnDragMove(SceneDragEvent(x,y,bytes.data(),bytes.length()));
		}
		*/
	}

	void SceneWindow::dragEnterEvent(QDragEnterEvent *evt)
	{
		int x=evt->pos().x();
		int y=evt->pos().y();
		
		assert(false);
		/*
		// accept just PQEngine mime format
		if (evt->mimeData()->hasFormat(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE))) {
			evt->acceptProposedAction();

			QByteArray bytes=evt->mimeData()->data(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE));
			
			SGameBuilder.OnDragEnter(SceneDragEvent(x,y,bytes.data(),bytes.length()));
			
		}
		*/
		
	}

	void SceneWindow::dropEvent(QDropEvent *evt)
	{
		int x=evt->pos().x();
		int y=evt->pos().y();
		
		assert(false);
		/*
		if (evt->mimeData()->hasFormat(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE))){
			
			QByteArray bytes=evt->mimeData()->data(QString::fromStdString(PQEngine::GameEngine::COMMAND_DATA_TYPE));
			
			SGameBuilder.OnDrop(SceneDragEvent(x,y,bytes.data(),bytes.length()));

			evt->acceptProposedAction();
		}
		*/
	}

	void SceneWindow::OnCreateObject(PQEngine::ObjectType type,int x,int y)
	{
		assert(false);
		//
		/*
		PQEngine::GameObject *obj=SEngine.selectObject(x,y);
		if(obj==NULL){
			if(PQEngine::GameObject::isComponent(type)){//component must attach to gameobject
				return;
			}
		}

		if(PQEngine::Object::isCollider(type)){
			if(!obj->isRigidBody()){
				//rigid body must attached before collider
				QMessageBox box;
				box.setText(QObject::tr("Rigid body must attached before any collider."));
				box.exec();
				return;
			}else{
				if(obj->hasCollider()){
					QMessageBox box;
					box.setText(QObject::tr("A Collider has already attached."));
					box.setInformativeText(QObject::tr("Do you want to replace it?"));
					box.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
					box.setDefaultButton(QMessageBox::Cancel);
					int ret=box.exec();
					switch (ret) {
					   case QMessageBox::Ok:
						   break;
					   case QMessageBox::Cancel:
						   // Cancel was clicked
						   return;
					 }
				}
			}
		}

		//GNgProjectManager.createObject(type,x,y);
		*/
	}

	void SceneWindow::OnAddResource(std::string path,int x,int y)
	{
		//GNgProjectManager.addSceneResource(path,x,y);
	}

}
